/* -----------------------------------------------------------------------
 *   Copyright (C) 2008 by Denjs
 *   dplsoft@pisem.net
 *   http://qdroid.berlios.de
 * -----------------------------------------------------------------------
 *   This program is free software licensed under GNU GPL License v.2 ; see main.cpp fo details
 *   Эта программа является свободным программным обеспечением; распространяемым под
 *   лицензией GNU General Public License v.2 (УНИВЕРСАЛЬНАЯ ОБЩЕСТВЕННАЯ ЛИЦЕНЗИЯ GNU версия 2.0) 
 * ----------------------------------------------------------------------- */
/*
 * t_BaseBot.cpp
 *
 *  Created on: 18.11.2008
 *      Author: Denjs
 */

#include "t_BaseBot.h"

//============================================================
t_BaseBot::t_BaseBot( t_FunctionRegistryItem *_FunctionRegItem, QObject *parent)
		: t_AbstractQDroidBot(parent)
{
	FunctionRegItem=_FunctionRegItem;
	BotId="Simple Bot, ID: 001 ver.2009.09.12";


}

//============================================================
/* needs to be redefined to make real class */
QString t_BaseBot::std_in(QString Message)
{

}


//============================================================
// далее - собственно полезные функции данного класса
//============================================================


//============================================================
// StdIn/StdOut/StdErr
//---------------------------------------------------------------------
//это поучатели - два от внутренних объъектов системы, один от "ядра"
/*/
void t_BaseBot::rcv_to_std_err(QByteArray Message) //--> подключен к сигналам внутренних объектов
{
 emit send_to_std_err(Message);//перешлем его
}/**/

//---------------------------------------------------------------------
/*/
void t_BaseBot::rcv_to_std_out(QByteArray Message) //--> подключен к сигналам внутренних объектов
{
 emit send_to_std_out(Message);//перешлем его
}/**/

//---------------------------------------------------------------------
//сделать функции потокобезопасными!
/*/
void t_BaseBot::rcv_from_std_in(QByteArray Message)// -> к нему подключен SIGNAL QDroid.rsv_from_std_in
{
 if (DebugLevel>=4) qDebug()<<"CP:t_BaseBot::rsv_from_std_in()[0055]";
 if (stdInCashMode)
    { 
	if (stdInCash.size()>maxCashSize)
	   {
		emit stdIn_CashOverflow();
	   };
	stdInCash.append(Message); 
	stdin_ReadyRead=true;
	emit stdIn_readyRead(); 
    }
    else emit send_from_std_in(Message);//перешлем его
    stdin_ReadyRead=false;
}
/**/

//---------------------------------------------------------------------
/*/

//сделать функции потокобезопасными!
//функция, не слот
QByteArray t_BaseBot::stdin_Read(int maxSize)// -> к нему подключен SIGNAL QDroid.rsv_from_std_in
{
	QByteArray baRez = stdInCash.left(maxSize);
	stdInCash=stdInCash.mid(maxSize);
	stdin_ReadyRead=false;
	return baRez;
}

int t_BaseBot::stdin_CashSize()// 
{
	return stdInCash.size();
}

//если "да" - то значит есть что читать.
// иначе - таймаут
bool t_BaseBot::sdtin_waitFirReadyRead(int maxTimeMs)// 
{
	bool rez=false;  //TIMER!!!!
	int countdown = maxTimeMs;

	if (stdInCashMode) return false;// не тот режим - всегда "нет"

	while (!stdin_ReadyRead)
	  {
		//QThread::msleep(100);
		SleepMS(100);
		if (countdown<0) return rez;
		countdown=countdown-100;
		QApplication::processEvents();
	  };
	rez=stdin_ReadyRead;
	return rez;
}

//спим в millisecinds!
int t_BaseBot::SleepMS( unsigned int time)
{	
	// Linux:
	#if defined (Q_WS_X11) 
			usleep(time*1000);//sleep in millisecinds 
	// Win:
	#elif defined (Q_WS_WIN)
			Sleep(time);//WIN  2008.02.19
	// Mac:
	#elif defined (Q_WS_MAC)
			// NOT SUPPORTED THIS VERSION 
	#else
			// NOT SUPPORTED THIS VERSION 
	#endif
	return 0;
};

/**/
//---------------------------------------------------------------------

/*/
//---------------------------------------------------------------------
void t_BaseBot::openStdReader() // -> запустить обработку потоков ввода
{
 emit send_openStdReader();//перешлем его
}

//---------------------------------------------------------------------
void t_BaseBot::closeStdReader()// -> остановить обработку потоков ввода-вывода
{
 emit send_closeStdReader();//перешлем его
}

//---------------------------------------------------------------------
void t_BaseBot::slot_stdInStream_Closed()
{
 emit sig_stdInStream_Closed();//перешлем его
}

//---------------------------------------------------------------------
//установить режим кеширования для чтения потока данных
// по умолчанию -  DataFlow
void t_BaseBot::slot_stdInSetCachedMode()
{
	stdInCashMode=true;
	emit changedCashMode(stdInCashMode);
}
//---------------------------------------------------------------------
//установить режим кеширования для чтения потока данных
// по умолчанию -  DataFlow
void t_BaseBot::slot_stdInSetDataFlowMode()
{
	stdInCashMode=false;
	emit changedCashMode(stdInCashMode);
}
/**/

//============================================================
//============================================================
QString t_BaseBot::say_hello()
{
	return QString("Hello! \n This is simple probe-bot for QTroid application.\n ");
	//return QString(QCoreApplication::applicationDirPath() );
}

//============================================================
QString t_BaseBot::scriptDirPath() //app_dir()
{
	//QDir Path=(QFileInfo(FunctionRegItem->fileName)).absoluteDir();//FunctionRegItem
	//return Path.absoluteFilePath();
//return QString(QCoreApplication::applicationDirPath() );
	return QString(FunctionRegItem->DirPath);
}

/*!TODO!*/
QString t_BaseBot::currentScriptName() //current Script file name
{
	return QString("");
}

QString t_BaseBot::applicationDirPath() //app_dir()
{
	return QString(QCoreApplication::applicationDirPath() );
}

QString t_BaseBot::temporallyDirPath() //app_dir()
{
	return QDir::tempPath();
	//return QString(QCoreApplication::applicationDirPath() );
}


QString t_BaseBot::currentPath() //app_dir()
{
	return QDir::currentPath();
	//return QString(QCoreApplication::applicationDirPath() );
}

QStringList t_BaseBot::getScriptArguments() //вернуть аргументы переданные скрипту (вероятно будет сконвертированно в массив)
{
	
	return this->arguments;
	//return QString(QCoreApplication::applicationDirPath() );
}

QString t_BaseBot::getPlatformVersion()
{
	return this->platformVersion;
}

//==================================
void t_BaseBot::send_std_out(QString Message) //оболочка для std_out дял непосредственного вызова из других функций
{
	//qDebug() << "t_BaseBot::send_std_out()::0044 :" << Message;
	emit std_out(Message);
}

//============================================================
int t_BaseBot::shell_execute(QString Command)
{
	//TODO: shell_execute:: ввести перехват консольного вывода программы. Пока вываливается на стандартную консоль программы.
	//TODO: !!! shell_execute:: ввести условную компиляцию для разных платформ
	QProcess *LocalProc;
	LocalProc = new QProcess();
	LocalProc->execute ( QString("cmd /C ")+ Command );
	return 0; //TODO shell_execute:: сделать анализ результатов выполнения
}

//============================================================
t_BaseBot* t_BaseBot::copy()
{
//not needed
}

//============================================================
//СТРОКИ:отсекание и разделение строк
//============================================================
QString t_BaseBot::str_mid(QString Source,int StartPos,int EndPos)
{
	return Source.mid(StartPos,EndPos);
}
//============================================================
QString t_BaseBot::str_right(QString Source,int Lenght)
{
	return Source.right(Lenght);
}
//============================================================
QString t_BaseBot::str_left(QString Source,int Lenght)
{
	return Source.left(Lenght);
}
//============================================================
//removes last symbols
QString t_BaseBot::str_chop(QString Source,int Lenght)
{
	Source.chop(Lenght);
	return Source;
}
//============================================================
//get splitted part
QString t_BaseBot::str_splitted_part(QString Source,QString Splitter, int PartNomber)
{
	// KeepEmptyParts =0 , Qt::CaseSensitive
	QStringList StrList=Source.split( Source,QString::KeepEmptyParts,Qt::CaseSensitive);
	return StrList.at(PartNomber);
}
// splitted part couer - на сколько частей можно разрезить эту строку
int t_BaseBot::str_splitted_part_couter(QString Source,QString Splitter)
{
	QStringList StrList=Source.split( Source,QString::KeepEmptyParts,Qt::CaseSensitive);
	return StrList.size();
}


//============================================================
//СТРОКИ:поиск и сравнение символов
//============================================================
bool t_BaseBot::str_starts_with(QString Source,QString FindStr)
{
	return Source.startsWith(FindStr);
}
//============================================================
bool t_BaseBot::str_ends_with(QString Source,QString FindStr)
{
	return Source.endsWith(FindStr);
}
//============================================================
//позиция подстроки после заданной
int t_BaseBot::str_index_of(QString Source,QString FindStr, int AfterPos)
{
	return Source.indexOf(FindStr,AfterPos,Qt::CaseSensitive);
}

//============================================================
//СТРОКИ:обработка символов в строках
//============================================================
QString t_BaseBot::str_trim(QString Source)
{
	return Source.trimmed();
}
//============================================================
QString t_BaseBot::str_to_lower(QString Source)
{
	return Source.toLower();
}
//============================================================
QString t_BaseBot::str_to_upper(QString Source)
{
	return Source.toUpper();
}
//============================================================
QString t_BaseBot::str_replace_str(QString Source,QString Before, QString After)
{
	Source.replace(Before, After);
}


//============================================================
//БазовыеДИАЛОГИ:
//============================================================
//-------------------------------------------------------------------------
int t_BaseBot::get_last_inputdialog_key()
{
    switch (LastInputDialogResult)
     {
		case QMessageBox::Ok: 			return 1; break;
		case QMessageBox::Open:			return 2; break;
		case QMessageBox::Save:			return 4; break;
		case QMessageBox::Cancel:		return 8; break;
		case QMessageBox::Close:			return 16; break;
		case QMessageBox::Discard:			return 32; break;
		case QMessageBox::Apply:			return 64; break;
		case QMessageBox::Reset:			return 128; break;
		case QMessageBox::RestoreDefaults:	return 256; break;
		case QMessageBox::Help:			return 512; break;
		case QMessageBox::SaveAll:		return 1024; break;
		case QMessageBox::Yes:			return 2048; break;
		case QMessageBox::YesToAll:		return 4096; break;
		case QMessageBox::No:			return 8192; break;
		case QMessageBox::NoToAll:		return 16384; break;
		case QMessageBox::Abort:		return 32769; break;
		case QMessageBox::Retry:		return 65536; break;
		case QMessageBox::Ignore:		return 131072; break;
		case QMessageBox::NoButton:		return 0; break;
	    default: return -1;
	 };//switch (LastInputDialogResult)
}

//private one
QMessageBox::StandardButtons t_BaseBot::get_std_buttons( int _BitFl)
{
	int BitFl=_BitFl;
	QMessageBox::StandardButtons RetValue=QMessageBox::NoButton;
     if (BitFl>=131072) { RetValue = RetValue | QMessageBox::Ignore; 	BitFl=BitFl-131072; };
   	 if (BitFl>=65536 ) { RetValue = RetValue | QMessageBox::Retry; 	BitFl=BitFl-65536;  };
   	 if (BitFl>=32769 ) { RetValue = RetValue | QMessageBox::Abort; 	BitFl=BitFl-32769;  };
   	 if (BitFl>=16384 ) { RetValue = RetValue | QMessageBox::NoToAll; 	BitFl=BitFl-16384;  };
   	 if (BitFl>=8192 ) { RetValue = RetValue | QMessageBox::No; 		BitFl=BitFl-8192;  };
   	 if (BitFl>=4096 ) { RetValue = RetValue | QMessageBox::YesToAll;	BitFl=BitFl-4096;  };
   	 if (BitFl>=2048 ) { RetValue = RetValue | QMessageBox::Yes; 		BitFl=BitFl-2048;  };
   	 if (BitFl>=1024 ) { RetValue = RetValue | QMessageBox::SaveAll; 	BitFl=BitFl-1024;  };
   	 if (BitFl>=512 ) { RetValue = RetValue | QMessageBox::Help; 		BitFl=BitFl-512;  };
   	 if (BitFl>=256 ) { RetValue = RetValue | QMessageBox::RestoreDefaults; BitFl=BitFl-256;  };
   	 if (BitFl>=128 ) { RetValue = RetValue | QMessageBox::Reset; 		BitFl=BitFl-128;  };
   	 if (BitFl>=64 ) { RetValue = RetValue | QMessageBox::Apply; 		BitFl=BitFl-64;  };
   	 if (BitFl>=32 ) { RetValue = RetValue | QMessageBox::Discard;		BitFl=BitFl-32;  };
   	 if (BitFl>=16 ) { RetValue = RetValue | QMessageBox::Close; 		BitFl=BitFl-16;  };
   	 if (BitFl>=8 ) { RetValue = RetValue | QMessageBox::Cancel; 		BitFl=BitFl-8;  };
   	 if (BitFl>=4 ) { RetValue = RetValue | QMessageBox::Save; 			BitFl=BitFl-4;  };
   	 if (BitFl>=2 ) { RetValue = RetValue | QMessageBox::Open; 			BitFl=BitFl-2;  };
   	 if (BitFl>=1 ) { RetValue = RetValue | QMessageBox::Ok; 			BitFl=BitFl-1;  };
//		case QMessageBox::NoButton:		return 0; break;
	return RetValue;
}

//-------------------------------------------------------------------------
// ввод текста
QString t_BaseBot::inputdialog_get_text(QString Header,QString Question, QString InitialValue)
{
	QString Res;
	bool ok;
	Res=QInputDialog::getText(NULL, Header, Question, QLineEdit::Normal, InitialValue, &ok);
	if (ok)
		LastInputDialogResult=QMessageBox::Ok;
	else
		LastInputDialogResult=QMessageBox::Cancel;

	return Res;
}

//-------------------------------------------------------------------------
// выбор элемента из списка
QString t_BaseBot::inputdialog_get_item(QString Header,QString Question, QString _ValueList)
{
	QString Res;
	QStringList Items=_ValueList.split(",");
	bool ok;
	Res=QInputDialog::getItem(NULL, Header, Question, Items, 0, false, &ok);

	if (ok)
		LastInputDialogResult=QMessageBox::Ok;
	else
		LastInputDialogResult=QMessageBox::Cancel;

	return Res;
}

//-------------------------------------------------------------------------

//-------------------------------------------------------------------------
int t_BaseBot::msgbox_information(QString Title,QString Text, int ButtonFlags)
{
	 LastInputDialogResult=QMessageBox::information ( NULL, Title, Text, get_std_buttons(ButtonFlags));
 	 return get_last_inputdialog_key();;
};
//-------------------------------------------------------------------------
int t_BaseBot::msgbox_question(QString Title,QString Text, int ButtonFlags)
{
	 LastInputDialogResult=QMessageBox::question ( NULL, Title, Text, get_std_buttons(ButtonFlags));
 	 return get_last_inputdialog_key();;
};
//-------------------------------------------------------------------------
int t_BaseBot::msgbox_warning(QString Title,QString Text, int ButtonFlags)
{
	 LastInputDialogResult=QMessageBox::warning( NULL, Title, Text, get_std_buttons(ButtonFlags));
 	 return get_last_inputdialog_key();;
};
//-------------------------------------------------------------------------
int t_BaseBot::msgbox_critical(QString Title,QString Text, int ButtonFlags)
{
	 LastInputDialogResult=QMessageBox::critical( NULL, Title, Text, get_std_buttons(ButtonFlags));
 	 return get_last_inputdialog_key();;
};


//
int t_BaseBot::messagebox(QString Text,QString InfoText, QString Detailes, int ButtonFlags)
{
	QString Res;
	int ret;
	bool ok;
    QMessageBox msgBox;
	 msgBox.setText(Text);
	 msgBox.setInformativeText(InfoText);
	 msgBox.setStandardButtons(get_std_buttons(ButtonFlags));
	 msgBox.setDetailedText(Detailes);

	 LastInputDialogResult=msgBox.information ( NULL, "title",Text, get_std_buttons(ButtonFlags));
	 ////msgBox.setDefaultButton(QMessageBox::Save);
	 //LastInputDialogResult = msgBox.exec();

 	 return get_last_inputdialog_key();;
}

bool t_BaseBot::isGuiUsed()
{
	return useGui;
}

//перекодировка байтовых данных в строку
QString t_BaseBot::ByteArrayToString(QByteArray line,QString CodecName)
{
    QString DBGPlace=QString("t_BaseBot::ByteArrayToString()");
    QString DefaultCodePage=QString("utf-8");
    QTextCodec *Codec = QTextCodec::codecForName(CodecName.toAscii());
    if (Codec==NULL)
     {
	   QString Msg="[WARNING] Codepage ["+CodecName+"] specified does not supported. Using Default codepage: ["+DefaultCodePage+"]";
	   //emit std_out(DBGPlace+":[0116]"+Msg);
	   if (DebugLevel>=2) qDebug()<<"DBG.L2::"<<DBGPlace<<":[0480]::"<<Msg;
	Codec = QTextCodec::codecForName(DefaultCodePage.toAscii()); //
     };
     return QString().append(Codec->toUnicode(line));
}

QByteArray t_BaseBot::StringToByteArray(QString line,QString CodecName)
{
/*/    QTextCodec *Codec = QTextCodec::codecForName(CurrentScriptCodePage.toAscii());
    if (Codec==NULL)
     {
		QString Msg="[WARNING] Codepage ["+CurrentScriptCodePage+"] specify in script-file does not supported. Using Default codepage: ["+DefaultCodePage+"]";
		emit std_out(DBGPlace+":[0116]"+Msg);
		if (DebugLevel>=2) qDebug()<<"DBG.L2::"<<DBGPlace<<":[0117]::"<<Msg;
    	Codec = QTextCodec::codecForName(DefaultCodePage.toAscii()); //
     };
	QString().append(Codec->toUnicode(line))
/**/
}




//===========================================================================
//STDIN, STDOUT, STDERR
//===========================================================================

//---------------------------------------------------------------------------
/*
int t_BaseBot::error_StdIn()
{
 	return stdIn.error();
}
*/
/*
Constant Value
QFile::NoError 0
QFile::ReadError 1
QFile::WriteError 2
QFile::FatalError 3
QFile::ResourceError 4
QFile::OpenError 5
QFile::AbortError 6
QFile::TimeOutError 7
QFile::UnspecifiedError 8
QFile::RemoveError 9
QFile::RenameError 10
QFile::PositionError 11
QFile::ResizeError 12
QFile::PermissionsError 13
QFile::CopyError 14

*/
